#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <cassert>

#define MAX_BUFFER_SIZE 10*1024*1024

/**
 * @brief 线程安全的环形缓冲区实现
 * 
 * 该缓冲区使用读写索引实现数据的循环存储，支持多线程环境下的数据读写操作
 * 通过原子操作和条件变量保证线程安全
 */
class Buffer {
private:
    // 读索引：标记当前可读数据的起始位置
    size_t _reader_idx;
    // 写索引：标记当前可写位置的起始位置
    size_t _writer_idx;
    // 缓冲区总容量
    size_t _capacity;
    // 存储数据的底层向量
    std::vector<char> _v;

public:
    /**
     * @brief 构造函数，初始化缓冲区
     * @param capacity 缓冲区容量，默认为MAX_BUFFER_SIZE
     */
    Buffer(size_t capacity = MAX_BUFFER_SIZE):
        _reader_idx(0), _writer_idx(0), 
        _capacity(capacity), _v(_capacity){}
    
    /**
     * @brief 判断缓冲区是否已满
     * @return true 已满，false 未满
     */
    bool full() { return _writer_idx == _capacity; }
    
    /**
     * @brief 判断缓冲区是否为空
     * @return true 为空，false 非空
     */
    bool empty() { return _reader_idx == _writer_idx; }
    
    /**
     * @brief 获取当前可读数据的大小
     * @return 可读数据的字节数
     */
    size_t readAbleSize() { return _writer_idx - _reader_idx; }
    
    /**
     * @brief 获取当前可写空间的大小
     * @return 可写空间的字节数
     */
    size_t writeAbleSize() { return _capacity - _writer_idx; }
    
    /**
     * @brief 重置缓冲区，清空所有数据
     */
    void reset() { _reader_idx = _writer_idx = 0; }
    
    /**
     * @brief 与另一个缓冲区交换内容
     * @param buf 要交换的缓冲区
     */
    void swap(Buffer &buf)  {
        _v.swap(buf._v);
        std::swap(_reader_idx, buf._reader_idx);
        std::swap(_writer_idx, buf._writer_idx);
        std::swap(_capacity, buf._capacity);
    }
    
    /**
     * @brief 向缓冲区写入数据
     * @param data 源数据指针
     * @param len 数据长度
     * @note 调用前需确保有足够的写入空间
     */
    void push(const char *data, size_t len) { 
        assert(len <= writeAbleSize());
        std::copy(data, data+len, &_v[_writer_idx]);
        _writer_idx += len;
    }
    
    /**
     * @brief 获取可读数据的起始指针
     * @return 指向可读数据的起始地址
     */
    const char* begin() { return &_v[_reader_idx]; }
    
    /**
     * @brief 标记指定长度的数据为已读
     * @param len 已读数据的长度
     */
    void pop(size_t len) { 
        _reader_idx += len; 
        assert(_reader_idx <= _capacity);
        // 当读写索引相遇时，表示缓冲区已空，重置索引
        if (empty()) reset();
    }
};